package cn.qingfeng.demo.transaction.springboot.aspect.service.impl;

import cn.qingfeng.demo.transaction.springboot.aspect.service.TransactionDemo3Service;
import cn.qingfeng.demo.transaction.springboot.common.entity.User;
import cn.qingfeng.demo.transaction.springboot.common.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.UUID;

/**
 * 两个有切面事务的方法进行嵌套，规则和两个声明式事务方法嵌套一样。private和内部调用会使事务失效。
 */
@Service
public class TransactionDemo3ServiceImpl implements TransactionDemo3Service {
    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private UserMapper userMapper;

    @Override
    public void addUser() {
        User user = new User("user", UUID.randomUUID().toString());
        userMapper.add(user);//回滚
        System.out.println("user向数据库中插入了User----" + user);

        System.out.println(1 / 0);
    }

    @Override
    public void plusUser() {
        User user = new User("user", UUID.randomUUID().toString());
        userMapper.add(user);//落表成功。不回滚。因为切面没有切到这个方法。
        System.out.println("user2向数据库中插入了User----" + user);

        System.out.println(1 / 0);
    }

    /**
     * 切面事务与声明式事务作用于同一个方法上时，相当于多层事务。切面事务作为外层事务，声明式事务作为内层事务。
     */
    @Transactional(propagation = Propagation.NEVER)
    @Override
    public void addUser2() {
        //下面的代码不会执行
        User user = new User("user", UUID.randomUUID().toString());
        userMapper.add(user);
        System.out.println("user2向数据库中插入了User----" + user);

        System.out.println(1 / 0);
    }

    /**
     * 切面事务与编程式事务同时存在时，相当于多层事务。切面事务作为外层事务，编程式事务作为内层事务。
     */
    @Override
    public void addUser3() {
        User user = new User("user", UUID.randomUUID().toString());
        userMapper.add(user);//回滚
        System.out.println("user3 outter向数据库中插入了User----" + user);

        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_NEVER);
        transactionTemplate.execute(status -> {
            //下面的代码不执行
            User user2 = new User("user2", UUID.randomUUID().toString());
            userMapper.add(user2);
            System.out.println("user3 inner向数据库中插入了User----" + user2);
            return true;
        });

        System.out.println(1 / 0);
    }

    /**
     * 声明式事务与编程式事务同时存在时，相当于多层事务。
     */
    @Transactional
    @Override
    public void plusUser2() {
        User user = new User("user", UUID.randomUUID().toString());
        userMapper.add(user);//回滚
        System.out.println("user outter向数据库中插入了User----" + user);

        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_NEVER);
        transactionTemplate.execute(status -> {
            //下面的代码不执行
            User user2 = new User("user2", UUID.randomUUID().toString());
            userMapper.add(user2);
            System.out.println("user2 inner向数据库中插入了User----" + user2);
            return true;
        });
    }
}
